package demo;
//将程序运行过程中出现的不正常行为--》异常
//异常代码分析
//Exception in thread "main" java.lang.ArithmeticException:（异常类型） / by zero（异常原因）
//        at demo.Test.main(Test.java:6)（发生异常代码的位置）
//异常是一个类
//异常分析：1--》点击控制台报错的代码中异常的种类，会跳转到该异常的源码，可根据源码的描述分析异常的种类和原因
//异常分析: 2--》 百度搜索  CSDN搜索 程序员网站--》stackoverflow
//语法错误不是异常（少些分号，中文括号……）
//在没有经过异常处理，一旦发生异常，程序直接结束（崩溃）
//异常的分类：不同时期的不同表现
//编译时异常  受查异常  在编译期间发生的异常
//运行时异常  非受查异常  在运行期间发生的异常

//异常体系
//        Throwable
//Error（错误）    Exception（异常）
//              编译时异常    运行时异常（RunTimeException）

//错误：必须程序员自己排查。指的是虚拟机无法解决的严重问题。如JVM的内部错误，资源耗尽，一旦发生回天乏力
//如果存在error，应该让程序直接崩溃
//异常:异常发生后程序员可以通过代码进行处理，使得程序继续执行。

//为什么声明了异常但是没处理在运行后程序不会崩溃？   因为此时虽然声明了异常，但是此时没1异常，所以不会崩溃。
//异常声明只是说明在这个位置有发生这个异常的可能性

//异常的处理
//防御性编程：在操作之前做充分的检查，每走一步检查一步--》事前防御性
//事后认错型：先操作，再看看有没有问题，有问题就处理。
//java异常处理 --》 try catch

//处理异常的前提：有异常--》你的触发或者抛出异常
//如何抛出异常--》throw
//代码自己执行过程中触发异常
//自己手动抛出异常---》一般用在抛出自定义异常

//throw必须写在方法的内部
//抛出的异常是exception或者exception的子类
//如果抛出的是运行时异常或者运行时异常的子类，则可以不用处理，交给JVM处理
//如果抛出编译时异常，用户必须自己处理，否则无法通过编译
//异常一旦抛出，后面的代码就不会执行---》抛出和捕获一样吗?

//如何捕获异常
//异常的捕获：异常的具体处理方式
//异常的捕获的方式：
//1---》异常的声明：声明方法会抛出什么样的异常，抛出异常会层层传递---》
//当不满足发生异常条件时，程序正常运行，当满足异常发生条件时，程序崩溃
//如果是异常声明，当我们没有实际解决这个异常的时候，我们就会把这个异常交给JVM去处理，一旦交给JVM，程序就崩溃了
//异常的声明：处在方法声明时参数列表之后，当方法中抛出编译时异常，用户不想处理，就可以借用throws将异常抛出，
//让方法的调用者去处理
//为什么这里声明的一定是编译时异常吗？  可以声明运行时异常，但好像没什么用
//可以声明受查异常，也可以声明非受查异常
//异常声明注意事项：
//1. throws必须跟在方法的参数列表之后
// 2. 声明的异常必须是 Exception 或者 Exception 的子类
// 3. 方法内部如果抛出了多个异常，throws之后必须跟多个异常类型，之间用逗号隔开，如果抛出多个异常类型具有父子关系，直接声明父类即可。


//调用声明了异常的方法时，用户必须对异常进行处理或者继续throws抛出，
//2---》catch捕获异常

//对于受查异常来说，当try块当中没有抛出异常的时候，这里检测不到受查异常就会报错
//try块抛出异常后，try块后面的代码不执行
//当catch没有捕获到异常时，异常会继续往外抛，直接给JVM接收到，由JVM处理，程序直接崩溃

//会不会同时抛出两个及以上的异常？ 不会。不会。在同一时间只会抛出一个异常。
//如果异常之间具有父子关系，一定要把子类写在前面，父类写在后面

//finally ---》finally一般用于资源的回收
//finally无论异常是否被捕获到，都要执行
public class Test {
    //错误Error 不是异常 StackOverError
    public static void func() {
        func();
    }


    public static void main1(String[] args) {
        int a = 10 / 0;// 算数异常
        int[] arr = null;
        System.out.println(arr.length);//空指针异常
        int[] arr1 = new int[3];
        System.out.println(arr1[10]);  //数组越界异常
        //类型转换异常
        //Aminal animal = new Dog();
        //Cat cat = (cat)animal;

    }
    public static void main2(String[] args) throws CloneNotSupportedException {
        Person person1 = new Person();
        Person person2 = (Person)person1.clone();

    }

//    "C:\Program Files\Java\jdk1.8.0_192\bin\java.exe" "-javaagent:C:\Program Files\IDEA\IntelliJ IDEA Community Edition 2021.3.2\lib\idea_rt.jar=3153:C:\Program Files\IDEA\IntelliJ IDEA Community Edition 2021.3.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_192\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_192\jre\lib\rt.jar;C:\JAVAcode\107-java\java112602\out\production\java112602" demo.Test
//    Exception in thread "main" java.lang.NullPointerException
//    at demo.Test.test1(Test.java:61)   上面才是我们需要解决的异常，解决了这个异常，下面的异常就没有问题了
//    at demo.Test.main(Test.java:66)

    public static void test1 (int[] a){
        if(a == null) {
            //
            throw new NullPointerException();
            //抛异常一般用在自己自定义的异常--》抛出自定义异常

        }

    }

    public static void main3(String[] args) {
        test1(null);
        System.out.println("haha");
    }

    public static void main4(String[] args){
        //对使用了声明异常的方法进行捕获处理
        Person person1 = new Person();

        try{
            Person person2 = (Person)person1.clone();
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
        }

    }

    public static void main4444(String[] args){
        //对使用了声明异常的方法进行捕获处理
        Person person1 = new Person();
//
//        try{
//            Person person2 = (Person)person1;
//        }catch(CloneNotSupportedException e){
//            e.printStackTrace();
//        }

    }

    public static void main44(String[] args) throws CloneNotSupportedException{
        //对使用了声明了异常的方法继续抛出
        Person person1 = new Person();
        Person person2 = (Person)person1.clone();
    }
    public static void test2() throws ArithmeticException{
        System.out.println(((int [])null).length);
    }

    public static void main5(String[] args) throws NullPointerException{
        test2();
        System.out.println("haha");
    }

    public static void test3()throws NullPointerException {
        System.out.println(((int [])null).length);
    }

    public static void test4()throws Exception {
        System.out.println(((int [])null).length);
    }

    //直接声明exception，看似方便，实际不行。因为不清楚异常的种类，就很难处理

    public static void main6(String[] args){
        try{
            test3();
        }catch (NullPointerException e) {
            e.printStackTrace();
        }

        System.out.println("haha");
    }

    public static void main7(String[] args) {
        try{
            //存放可能抛出异常的代码
            test1(null);
        }catch(NullPointerException e) {
            e.printStackTrace();
            //对异常的处理
        }
        System.out.println("正常的逻辑");
    }


    public static void main8(String[] args) {
        System.out.println("hahhhh");
        try{
            test7(null);
        }catch (NullPointerException e) {
            e.printStackTrace();
        }

    }

    public static void test7(int[] a) {
        if(a == null) {
            throw new NullPointerException();
            //异常会抛回去给调用者，所以此处异常抛回给main方法，有main方法进行try catch
        }
    }

    public static void main9(String[] args) {
        try{

        }catch(NullPointerException |
                ArithmeticException |
                ArrayIndexOutOfBoundsException e) {
            //一行可以写完所有异常，但是不知道是哪个异常
        }
    }

    public static void main10(String[] args) {
//        try{
//
//        }catch(Exception e){
//            exception会捕获所有异常，所以放在最前面，它可以捕获所有的异常
//            如果把他放到catch的第一个，那么后续的异常没有任何的作用了，所以此处会报错
//              所以exception要放在最后，对异常捕获进行兜底
//        }catch(NullPointerException e) {
//
//        }
    }

    public static void main11(String[] args) {
        try{

        }catch(Exception e) {
            //看似方便，但是不知道到底是哪个异常，所以是错误的代码，不好的代码
            //不可取的
        }
    }

    //当try当中存在多个异常的时候，从上往下执行，谁先抛出异常就捕获那个异常
    //catch当中的catch捕获顺序不影响异常的捕获
    public static void main(String[] args) {


    }
    //不建议在finally当中写return语句，因此finally的return会覆盖原来的return值
    //这种情况之会报警告，不会报错


    //throw  抛出异常
    //throws  声明异常

    //异常的处理流程
    //方法之间是相互调用的，如果本方法没有合适的异常处理方法，
    //则异常会沿着方法关系传递（异常可以传递），沿着调用栈传递
    //如果传递到最后都没有方法处理异常，则异常会被交给JVM

    //程序先执行try中的代码，如果try中的代码出现异常，





}

class Person implements Cloneable{
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
